const sRoot = __dirname;
const osFs = require('fs');
const osPath = require('path');
const { spawn: osSpawn } = require('child_process');
const oSloc = require('sloc');
const oEJS = require('ejs');
const { fnWriteFile } = require('../utils/fs');


class SlocChecker {
  constructor() {
    this.oResLst = {}; // 单个文件的记录集
    this.oAggregate = {}; // 合计
    this.sReportPath;
  }

  fnCheck({ aFileList }) {

    const oSlocResult = aFileList.reduce(
      (oPrev, sItem) => {
        const oFileContent = osFs.readFileSync(sItem, 'utf-8');
        const sSlocType = this.fnGetSlocTypeFromFilepath(sItem);
        const oFileSlocResult = oSloc(oFileContent, sSlocType);
        if((sItem.includes(".js") || sItem.includes(".vue") || sItem.includes(".tsx") || sItem.includes(".ts")) && (oFileSlocResult['source'] > oFileSlocResult['comment'])) {
          this.oResLst[sItem] = {
            ...oFileSlocResult,
            "percentage":  Math.floor(((oFileSlocResult['comment'] + oFileSlocResult['mixed']) / oFileSlocResult['source']).toFixed(2) * 100)
          }

          // 所有数据合计
          Object.keys(oPrev).forEach((sKey) => {
            oPrev[sKey] += oFileSlocResult[sKey];
          });
        }
        return oPrev;
      },
      {
        // 初始化传入对象给oPrev，做统计
        total: 0,
        source: 0,
        comment: 0,
        single: 0,
        block: 0,
        mixed: 0,
        empty: 0,
        todo: 0,
      }
    );

    this.oAggregate = {
      total: oSlocResult.total, // 业面总行数
      source: oSlocResult.source, // 代码总行数
      comment: oSlocResult.comment, // 总备注行数
      single: oSlocResult.single, // 单行备注行数
      block: oSlocResult.block, // 多行备注行数
      mixed: oSlocResult.mixed, // 混合注释，代码后面的注解
      empty: oSlocResult.empty, // 空行
      todo: oSlocResult.todo, // todo的注释
    };
  }

  fnReport({sReportPath, sFormat}) {
    const oRes = {};
    // 文件记录统计
    oRes['formats'] = this.oResLst;
    oRes['solc'] = this.oAggregate;

    if(sFormat === 'html') {
      this.fnOutputHtml(sReportPath);
    } else {
      const sJsonPath = osPath.join(sReportPath, 'sloc-report.json');
      this.fnWriteFile(sJsonPath, JSON.stringify(oRes, null, 2));
    }
    return 'success';
  }

  async fnOutputHtml(sReportPath){
    const sTplPath = osPath.join(sRoot, '../html-tpl/sloc.html');
    const sOutPutPath  = osPath.join(sReportPath, 'sloc.html');
    const {total,source, comment, single, block, mixed, empty, todo} = this.oAggregate;

    await oEJS.renderFile(sTplPath, {
      total: total, // 业面总行数
      source: source, // 代码总行数
      comment: comment, // 总备注行数
      single: single, // 单行备注行数
      block: block, // 多行备注行数
      mixed: mixed, // 混合注释，代码后面的注解
      empty: empty, // 空行
      todo: todo, // todo的注释

      oResLst: this.oResLst,
      oResLstKeys: Object.keys(this.oResLst),
    }, function (oErr, sData) {
      if (oErr) { throw new Error(oErr); }
      fnWriteFile(sOutPutPath, sData);
    });

    return true;
  }

  fnGetSlocTypeFromFilepath(sFilepath) {
    const sExtname = osPath.extname(sFilepath).slice(1);
    return sExtname === 'vue' ? 'html' : sExtname;
  }
}

module.exports = SlocChecker;
